#include "udfimporter.h"
#include "./db/dbwriter.h"
#include "./udf/universaldataformat.h"
#include "./db/dbconnection.h"
#include "udfexception.h"

#include <QFileInfo>
#include <QDate>
#include <QVector>

#include <fstream>
using namespace std;


int UdfImporter::_createPolygon(QString description)
{
    PolygonRecord polygon;
    polygon.description = description;
    polygon.idMeasurementType = MEASUREMENT_TYPE_COAXIAL;

    DbWriter dbWriter;
    int idPolygon = dbWriter.addSingleRecord(&polygon);
    if(idPolygon < 0)
    {
        throw UdfException("Can't create polygon");
    }

    return idPolygon;
}

int UdfImporter::_createFakeLoop(int idPolygon)
{
    LoopReecord loop;    
    loop.centerX = 0;
    loop.centerY = 0;
    loop.current = 1.0;
    loop.idLoopForm = LOOP_FORM_CIRCLE_ID;
    loop.idPolygon = idPolygon;
    loop.size = 1.0;
    loop.turnAngle = 0.0;
    loop.turnsNumber = 1;

    DbWriter dbWriter;
    int idLoop = dbWriter.addSingleRecord(&loop);
    if(idLoop < 0)
    {
        throw UdfException("Can't create loop");
    }

    return idLoop;
}

int UdfImporter::_createPicket(int idEmf, int idLoop, double x, double y, double z, double height)
{
    PicketRecord picket;
    picket.x = x;
    picket.y = y;
    picket.z = z;
    picket.height = height;
    picket.idEmf = idEmf;
    picket.idGeneratorLoop = idLoop;

    DbWriter dbWriter;
    int idPicket = dbWriter.addSingleRecord(&picket);
    if(idPicket < 0)
    {
        throw UdfException("Can't create picket");
    }

    return idPicket;
}

int UdfImporter::_createEmf(double* emfTimes, double* emfValues, int emfPointsNumber, float timeMultiplier)
{
    int idEmf = EmfRecord().createId();
    if(idEmf < 0)
    {
        throw UdfException("Can't create EMF id");
    }

    QVector<BulkInsertRecord *> emf;
    try
    {
        for(int i=0; i<emfPointsNumber; i++)
        {
            EmfRecord *emfRecord = new EmfRecord;
            emfRecord->idEmf = idEmf;
            emfRecord->time = emfTimes[i]*timeMultiplier;
            emfRecord->value = emfValues[i];
            emf.push_back(emfRecord);
        }

        DbWriter dbWriter;
        if(!dbWriter.addMultipleRecords(emf))
        {
            throw UdfException("Can't create EMF");
        }
    }
    catch(UdfException exc)
    {
        for(int i=0; i<emf.size(); i++)
            delete emf[i];

        throw exc;
    }

    for(int i=0; i<emf.size(); i++)
        delete emf[i];

    return idEmf;
}

void UdfImporter::importFromFile(QString &filePath, ProgressObserver *observer)
{
    QFileInfo inputFileInfo(filePath);
    if(!inputFileInfo.exists())
    {
        throw UdfException("Can't open the file");
    }

    if(observer)
        observer->reportProgress(0);
    QSqlDatabase db = DbConnection::instance()->getDb();
    if(!db.transaction())
    {
        throw UdfException("Can't begin transaction");
    }

    int idPolygon = _createPolygon(inputFileInfo.fileName() + "_____" + QDateTime::currentDateTime().toString());
    int idLoop = _createFakeLoop(idPolygon);


    int frameNumber = 0;

    ifstream file(filePath.toUtf8().constData(), ios::binary);

    float timeMultiplier = 1;
    bool multiplierSet = false;
    int framesCount = 0;
    do
    {
        frameNumber++;
        UniversalDataFrame frame;

        if(!frame.Load(file)) break;
        if(frame.Header.EMFExist)
        {
            for(int nChannel = 0; nChannel < frame.EMF.NumberOfChannels; nChannel++)
            {
                double* emfTimes = frame.EMF.Channels[nChannel].Times;
                double* emfValues = frame.EMF.Channels[nChannel].Values;
                int emfPointsNumber = frame.EMF.Channels[nChannel].PointsNumber;

                if(emfTimes[0] <= 0.0)
                {
                    emfTimes++;
                    emfValues++;
                    emfPointsNumber--;
                }

                if(!multiplierSet)
                {
                    if(emfTimes[emfPointsNumber-1] < 0.1)
                    {
                        timeMultiplier = TIME_MULTIPLIER;
                    }

                    size_t bytesRead = file.tellg();
                    size_t bytesTotal = inputFileInfo.size();
                    framesCount = bytesTotal / bytesRead + 1;

                    multiplierSet = true;
                }



                int idEmf = _createEmf(emfTimes, emfValues, emfPointsNumber, timeMultiplier);
                _createPicket(idEmf, idLoop, frame.x, frame.y, 0, frame.z);
            }
        }

        if(observer)
        {
            int progress = (frameNumber*100)/framesCount;
            observer->reportProgress(progress);
        }
    }
    while(1);

    db.commit();

    if(observer)
        observer->reportProgress(100);

    file.close();
}
